using System;
using System.Collections.Generic;
using System.IO;
using System.Security.Cryptography;
using System.Text;
using System.Text.Json;
using JlPay.Sdk.Core;
using JlPay.Sdk.Services;
using JlPay.Sdk.Utils;

namespace JlPay.Sdk.Models
{
    /// <summary>
    /// 文件上传请求基类
    /// </summary>
    public abstract class FileUploadRequest : IRawMapGetter
    {
        /// <summary>
        /// 元数据
        /// </summary>
        public string? Meta { get; set; }

        /// <summary>
        /// 文件路径
        /// </summary>
        public string? FilePath { get; set; }

        /// <summary>
        /// 文件内容
        /// </summary>
        public byte[]? FileContent { get; set; }

        /// <summary>
        /// 文件名
        /// </summary>
        public string? FileName { get; set; }

        /// <summary>
        /// 原始请求Map
        /// </summary>
        private Dictionary<string, object>? _rawMap;

        /// <summary>
        /// 从文件路径设置文件
        /// </summary>
        public FileUploadRequest SetFileFromPath(string filePath)
        {
            FilePath = filePath;
            FileName = Path.GetFileName(filePath);
            
            if (File.Exists(filePath))
            {
                FileContent = File.ReadAllBytes(filePath);
                SetMetaWithDigest(FileName!, FileContent);
            }
            
            return this;
        }

        /// <summary>
        /// 设置文件内容
        /// </summary>
        public FileUploadRequest SetFile(byte[] fileContent, string fileName)
        {
            FileContent = fileContent;
            FileName = fileName;
            SetMetaWithDigest(fileName, fileContent);
            return this;
        }

        /// <summary>
        /// 设置包含摘要的元数据（参考PHP版本的setMetaWithDigest方法）
        /// </summary>
        /// <param name="fileName">文件名</param>
        /// <param name="fileContent">文件内容</param>
        private void SetMetaWithDigest(string fileName, byte[] fileContent)
        {
            // 计算文件内容的SM3摘要
            string digest;
            try
            {
                var hashBytes = SmUtils.GetDigestByType("SM3", fileContent);
                // PHP版本返回Base64编码，我们需要转换为Base64
                digest = Convert.ToBase64String(hashBytes);
            }
            catch (Exception ex)
            {
                // 如果SM3计算失败，使用SHA256作为备选
                using var sha256 = SHA256.Create();
                var hashBytes = sha256.ComputeHash(fileContent);
                digest = Convert.ToBase64String(hashBytes);
            }

            // 构建完整的meta信息，与PHP版本完全一致
            var meta = new Dictionary<string, object>
            {
                ["filename"] = fileName,
                ["alg"] = "SM3", // 摘要算法
                ["abstract"] = digest // 文件摘要（Base64编码）
            };

            Meta = JsonSerializer.Serialize(meta, new JsonSerializerOptions
            {
                PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower
            });
        }

        /// <summary>
        /// 设置基本元数据（保留原有方法以兼容）
        /// </summary>
        /// <param name="fileName">文件名</param>
        /// <param name="fileContent">文件内容</param>
        private void SetMeta(string fileName, byte[] fileContent)
        {
            var meta = new Dictionary<string, object>
            {
                ["filename"] = fileName,
                ["content_length"] = fileContent.Length,
                ["content_type"] = GetContentType(fileName)
            };

            Meta = JsonSerializer.Serialize(meta, new JsonSerializerOptions
            {
                PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower
            });
        }

        /// <summary>
        /// 获取内容类型
        /// </summary>
        private static string GetContentType(string fileName)
        {
            var extension = Path.GetExtension(fileName).ToLowerInvariant();
            return extension switch
            {
                ".jpg" or ".jpeg" => "image/jpeg",
                ".png" => "image/png",
                ".gif" => "image/gif",
                ".bmp" => "image/bmp",
                ".webp" => "image/webp",
                ".mp4" => "video/mp4",
                ".avi" => "video/x-msvideo",
                ".mov" => "video/quicktime",
                ".pdf" => "application/pdf",
                _ => "application/octet-stream"
            };
        }

        /// <summary>
        /// 获取API URI
        /// </summary>
        public abstract string GetApiUri();

        /// <summary>
        /// 获取原始请求Map
        /// </summary>
        public (Dictionary<string, object> rawMap, bool exists) GetRawMap()
        {
            if (_rawMap == null)
            {
                _rawMap = new Dictionary<string, object>();
                
                // 添加meta字段，确保签名内容完整
                if (!string.IsNullOrEmpty(Meta))
                    _rawMap["meta"] = Meta;
                
                // 添加文件名，用于签名验证
                if (!string.IsNullOrEmpty(FileName))
                    _rawMap["filename"] = FileName;
            }

            return (_rawMap, true);
        }
    }

    /// <summary>
    /// 图片上传请求
    /// </summary>
    public class ImageUploadRequest : FileUploadRequest
    {
        /// <summary>
        /// 获取API URI
        /// </summary>
        public override string GetApiUri()
        {
            return "/base/file/upload/image";
        }
    }

    /// <summary>
    /// 视频上传请求
    /// </summary>
    public class VideoUploadRequest : FileUploadRequest
    {
        /// <summary>
        /// 获取API URI
        /// </summary>
        public override string GetApiUri()
        {
            return "/base/file/upload/video";
        }
    }

    /// <summary>
    /// PDF上传请求
    /// </summary>
    public class PdfUploadRequest : FileUploadRequest
    {
        /// <summary>
        /// 获取API URI
        /// </summary>
        public override string GetApiUri()
        {
            return "/base/file/upload/pdf";
        }
    }

    /// <summary>
    /// 文件上传响应
    /// </summary>
    public class FileUploadResponse : StandardResponse
    {
        /// <summary>
        /// 文件URL
        /// </summary>
        public string? FileUrl { get; set; }

        /// <summary>
        /// 媒体文件ID
        /// </summary>
        public string? MediaId { get; set; }

        /// <summary>
        /// 获取文件URL
        /// </summary>
        public string GetFileUrl()
        {
            return FileUrl ?? string.Empty;
        }

        /// <summary>
        /// 获取媒体文件ID
        /// </summary>
        public string GetMediaId()
        {
            return MediaId ?? string.Empty;
        }
    }
} 